import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;


public class WorldGen implements ActionListener
{
	//OVERGROUND
	//Space level: Ft: 840-1200 Block:420-600 Higher Float Islands 1/2/3 at 840-1000
	//Air level: Ft: 480-840 Block: 240-420 Lower Float Islands 2/3/3 at 480-840
	//
	//SURFACE-"BLOCS" WILL BE DESIGNATED BEFORE GENERATION SO NO OVERLAPS
	//Dirt level: Ft: 0-480 Block: 0-240
	//	Forest: Default, spawn first >Sunflowers, Grass, Trees, Mushrooms >Dirt, Clay veins, stone random >Copper, Iron, Silver, Gold
	//								 >Water >Ft: 360-480 Block: 180-240
	//	Desert: Spawn by "bomb morphing" + random sand raining
	//	Corruption: 7-9/9-12/12-14 pits per corruption, will be spawned by clearing circles downward at random intervals.  2/3 chance of dark orb per pit.
	//	Meteorite: Bomb morphing dirt terrain + filling in holes, lottery occurrence
	//	Surface jungle: Spread morphing dirt terrain into mud, cluster rain jungle seeds, spread seeds.
	//	Ocean: 480 blocks inward from sides of map is start point of ocean, clear out slant slope of ~ 2.5 {random down, side 1-4] Sand bombing every ocean surface + 120-360 feet in from shore/creation point.
	//				WATER GENESIS on all blocks cleared side from shore. Shore side will be .5 height water.
	//	Dungeon entrance: Top of ground will be cleared/flattened to build preset dungeon top, horizontal line bulldozing will be done to clear path down[slope 1/2-1/3]. 
	//
	//
	//
	//
	//
	//
	//
	public static Random r = new Random();
	protected JLabel txt = new JLabel("Enter your desired world's name.");
	protected JLabel txt2 = new JLabel("Select your desired world's size.");
	protected JButton confirm = new JButton("Confirm!");
	JTextField field = new JTextField("Default");
	String[] arr = {"Tiny", "Small", "Medium", "Large"};
	JComboBox dropdown = new JComboBox(arr);
	public WorldGen()
	{
		JFrame f = new JFrame();
		f.setLayout(new GridLayout(5,1));
		f.setResizable(false);
		f.add(txt);
		f.add(field);
		f.add(txt2);
		f.add(dropdown);
		f.add(confirm);
		f.setVisible(true);
		f.setResizable(false);
		f.setLocation(0, 150);
		f.setSize(300, 150);
		confirm.addActionListener(this);
	}
	static World makeWorld(int size, String s)//1-> small, 2-> medium, 3-> large
	{
		World newWorld;
		switch(size)
		{
		case 0: newWorld = new World(2100,600, 0); break;
		case 1: newWorld = new World(4200,1200, 1); break;
		case 2: newWorld = new World(6400,1800, 2); break;
		default: newWorld = new World(8400,2400, 3); break;
		}
		newWorld.worldName=s;
		makeSurface(newWorld);
		System.out.println("Surface generated");
		fillSurface(newWorld);//Might add mountain creation
		rectMorph(0, 0, newWorld.width-1, (int)(newWorld.height*.75), Blocks.DIRT, newWorld);
		System.out.println("Surface filled");
		datOcean(newWorld);
		setSpawn(newWorld);
		return newWorld;
	}
	static World makeWorld(int size)
	{
		String s = null;
		switch(size)
		{
		case 0: s = "Tiny World"; break;
		case 1: s = "Small World"; break;
		case 2: s = "Medium World"; break;
		default: s = "Large World"; break;
		}
		return makeWorld(size, s);
	}
	static void makeSurface(World w)
	{
		int nextY = (int)(w.height*.8)+r.nextInt((int)(w.height*.025));
		for(int i = 0; i<w.width;i++)
		{
			w.fgTransmuteTo(i, nextY, Blocks.DIRT);
			int updown;
			boolean up = true;
			double shift = Math.random();
			if (shift<.5){updown = 0;} else if (shift<.85) {updown=1;} else if (shift<.9) {updown=2;} else if (shift<.94) {updown=3;} else if (shift<.97) {updown=4;} else if (shift<.99) {updown=5;}  else if (shift<.994) {updown=6;} else if (shift<.997) {updown=7;} else if (shift<.999) {updown=8;} else {updown = 9;}
			double downchance = (((double)nextY)-((double)w.height)*.775)/(((double)w.height)*.05);
			if (Math.random()<downchance) {up = false;}
			if (up) {nextY=nextY+updown;} else {nextY= nextY-updown;}
		}
	}
	static void fillSurface(World w)
	{
		for(int i = 0; i<w.width;i++)
		{
			for(int j = (int)(.75*w.height); (w.foreground[i][j].type!=Blocks.DIRT) ;j++)
			{
				w.fgTransmuteTo(i, j, Blocks.DIRT);
			}
		}
	}
	static void datOcean(World w)
	{	
		//left side
		int startingY=0;
		int startingX = (int)(.06*w.width);
		for(int i=w.height-1; i>0; i--)
		{	
			if (w.foreground[startingX][i].type!=Blocks.EMPTY)
			{
				startingY = i;
				i=0;
			}
		}
		startingX-=10+20*Math.random();
		startingY-=5+3*Math.random();
		rectMorph(0,startingY+1,startingX,w.height-1,Blocks.EMPTY,w);
		rectMorph(0,(int)((double)w.height*.75),startingX-1,startingY,Blocks.DIRT,w);
		while (startingX>0)
		{
			clearLineForOcean(w,startingX,startingY,true);
			startingX-=1+3*Math.random();
			startingY--;
		}
		for(int i = 0;i<(int)(.06*w.width);i++)
		{
			nukeStraightDown(w,i,Blocks.SAND,15,25,true);
		}
		//right side
		startingY=0;
		startingX=(int)(.94*w.width);
		for(int i=w.height-1; i>0; i--)
		{	
			if (w.foreground[startingX][i].type!=Blocks.EMPTY)
			{
				startingY = i;
				i=0;
			}
		}
		startingX+=10+20*Math.random();
		startingY-=5+3*Math.random();
		rectMorph(startingX,startingY+1,w.width-1,w.height-1,Blocks.EMPTY,w);
		rectMorph(startingX+1,(int)((double)w.height*.75),w.width-1,startingY,Blocks.DIRT,w);
		while (startingX<w.width)
		{
			clearLineForOcean(w,startingX,startingY,false);
			startingX+=1+3*Math.random();
			startingY--;
		}
		for(int i = (int)(.94*w.width);i<w.width;i++)
		{
			nukeStraightDown(w,i,Blocks.SAND,15,25,true);
		}

	}
	static void bombMorph(World w, int x, int y, int type, int r, float chance, boolean existingonly)//if EO false, then bomb change all
	{
		for(int i = x-r; i<=x+r;i++)
		{
			for(int j = y-r; j<=y+r; j++)
			{
				if((x>=0)&&(x<w.width)&&(y>=0)&&(y<w.height))
				{
					if ((Math.sqrt(Math.pow(i-x,2)+Math.pow(j-y,2)))<=(r))
					{
						if(Math.random()<chance)
						{
							try{
							if((existingonly)&&(w.foreground[i][j].type!=Blocks.EMPTY))
							{w.fgTransmuteTo(i, j, type);}
							else if (!(existingonly))
							{w.fgTransmuteTo(i, j, type);}}catch(Exception e){}
						}
					}
				}
			}
		}
	}
    static void rectMorph(int xstart, int ystart, int xend, int yend, int type, World w)//BOTTOM LEFT CORNER TO TOP RIGHT CORNER
    {
    	for(int i = xstart; i<=xend; i++)
	    {
    		for (int j= ystart; j<=yend;j++)
    		{
    			w.fgTransmuteTo(i,j,type);
		    }
	    }
    }
    static void nukeStraightDown(World w, int x, int type, int r1, int r2, boolean EO)
    {
    	int y = 0;
    	for(int i=w.height-1; i>0; i--)
    	{	
    		if (w.foreground[x][i].type!=Blocks.EMPTY)
    		{
    			y=i;
    			i=0;
    		}
    	}
    	bombMorph(w,x,y,type,(int)(r1+Math.random()*(r2-r1+1)), 1,EO);
    }
    static void lineStraightDown(World w, int x, int type, int l1, int l2, boolean EO)
    {
    	int y = 0;
    	for(int i=w.height-1; i>0; i--)
	    {	
		if (w.foreground[x][i].type!=Blocks.EMPTY)
		    {
			y=i;
			i=0;
		    }
	    }
	for(int i=0;i<((int)(l1+Math.random()*(l2-l1+1)));i++)
	    {
			w.fgTransmuteTo(x,y-1,Blocks.SAND);
	    }
    }
    static void createDesert(World w, int leftmostX, int width, int l1, int l2)
    {
    }
    static void createVeins(World w, int x, int y, int algorithm, int type)
    {
    
    }
    static void demCaves(World w)
    {
    	
    }
    static void clearLineForOcean(World w, int x, int y, boolean left)
	{
	    if (left)
		{
		    for(int i = 0; i<x; i++)
			{
			    w.fgTransmuteTo(i,y,Blocks.EMPTY);
			    w.addWater(i,y,1);
			}
		}
	    else
		{
		    for(int i = x; i<w.width; i++)
			{
			    w.fgTransmuteTo(i,y,Blocks.EMPTY);
			    w.addWater(i,y,1);
			}
		}
	}
    static void setSpawn(World w)
    {
    	int y;
    	int x = (w.width/2)-1;
    	for(y=w.height-1; y>0; y--)
	    {	
    		if (w.foreground[x][y].type!=Blocks.EMPTY||w.foreground[x+1][y].type!=Blocks.EMPTY)
    		{break;}
	    }
    	w.defXSpawn = x*16;
    	w.defYSpawn = (y+1)*16-1;    	
    }
	public void actionPerformed(ActionEvent e)
	{
		String s = (String)(dropdown.getSelectedItem());
		World w = null;
		if(s.equals("Tiny"))
		{
			w = makeWorld(0,s);
		}
		else if (s.equals("Small"))
		{
			w = makeWorld(1,s);
		}
		else if (s.equals("Medium"))
		{
			w = makeWorld(2,s);
		}
		else
		{
			w = makeWorld(3,s);
		}
		w.save();
	}
}
	